﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using NCM_MSTest.Alg;

namespace NCM_MSTest
{
    [TestClass]
    [TestCategory("数值积分与微分")]
    public class 数值积分与微分
    {
        [TestMethod]
        public void Example_5_1_5_2()
        {
            F f = new F(x => Math.Sin(x) / x);
            double a = 0.1;
            double b = 4;
            double h = 0.3;
            double StandardI = 1.6576;
            double StandardX = 1.6582;
            double I1, I2, I3;
            double eps = 1e-4;
            //矩形求积 误差比较大 因此缩小积分步长
            NumbericalIntegrationDifferentiation.Integral_Rectangle(f, a, b, h / 100, out I1);
            NumbericalIntegrationDifferentiation.Integral_Trapezoidal(f, a, b, h, out I2);
            NumbericalIntegrationDifferentiation.Integral_Trapezoidal_InvariableStep(f, a, b, eps, out I3);

            Console.WriteLine($"标准值：{StandardI}\t {StandardX}");
            Console.WriteLine($"矩形求积     :\t{I1}");
            Console.WriteLine($"梯形求积     :\t{I2}");
            Console.WriteLine($"变步长梯形求积:\t{I3}");
            Assert.IsTrue(I1.EqualsEx(StandardI, 1e-2));
            Assert.IsTrue(I2.EqualsEx(StandardI, 1e-4));
            Assert.IsTrue(I3.EqualsEx(StandardX, eps));
        }

        [TestMethod]
        public void Example_5_3_5_4()
        {
            F f = new F(x => Math.Sin(x) / x);
            double a = 0.1;
            double b = 4;
            double h = 0.15;
            double StandardX = 1.6583;
            double I1, I2, I3;
            double eps = 1e-4;
            NumbericalIntegrationDifferentiation.Integral_Simpson(f, a, b, h, out I1);
            NumbericalIntegrationDifferentiation.Integral_Simpson_Optimize(f, a, b, h, out I2);
            NumbericalIntegrationDifferentiation.Integral_Simpson_InvariableStep(f, a, b, eps, out I3);

            Console.WriteLine($"标准值          ：\t{StandardX}");
            Console.WriteLine($"辛普森求积       :\t{I1}");
            Console.WriteLine($"辛普森求积（优化）:\t{I2}");
            Console.WriteLine($"变步长辛普森求积  :\t{I3}");
            Assert.IsTrue(I1.EqualsEx(StandardX, 1e-3));
            Assert.IsTrue(I2.EqualsEx(StandardX, 1e-3));
            Assert.IsTrue(I3.EqualsEx(StandardX, 1e-4));
        }

        [TestMethod]
        public void Example_5_5_5_6()
        {
            F f = new F(x => Math.Sin(x) / x);
            double a = 0.1;
            double b = 4;
            double h = 0.10;
            double StandardX = 1.6583;
            double I1, I2, I3;
            double eps = 1e-4;
            NumbericalIntegrationDifferentiation.Integral_NewtonCotes(f, a, b, h, out I1);
            NumbericalIntegrationDifferentiation.Integral_NewtonCotes_N(f, a, b, h, 3, out I2);
            //NumbericalIntegrationDifferentiation.Integral_Simpson_InvariableStep(f, a, b, eps, out I3);

            NumbericalIntegrationDifferentiation.Integral_Romberg(f, a, b, eps, out I3);

            Console.WriteLine($"标准值              ：\t{StandardX}");
            Console.WriteLine($"牛顿-柯特斯 求积     :\t{I1}");
            Console.WriteLine($"牛顿-柯特斯(N=3) 求积:\t{I2}");
            Console.WriteLine($"龙贝格公式 求积      :\t{I3}");
            //Console.WriteLine($"变步长辛普森求积  :\t{I3}");
            Assert.IsTrue(I1.EqualsEx(StandardX, 1e-3));
            Assert.IsTrue(I3.EqualsEx(StandardX, 1e-3));
            //Assert.IsTrue(I2.EqualsEx(StandardX, 1e-3));
            //Assert.IsTrue(I3.EqualsEx(StandardX, 1e-4));

        }

        [TestMethod]
        public void Example_5_7()
        {
            FF f = new FF((x, y) => Math.Pow(x, 3) + Math.Pow(y, 3));
            double[] ab = new double[] { 0, 2 };
            double[] cd = new double[] { 0, 1 };
            int n = 10;
            int m = 20;
            double StandardX = 4.50000;
            double I1, I2, I3;
            double eps = 1e-4;
            NumbericalIntegrationDifferentiation.Integral_Simpson_xy(f, ab[0], ab[1], cd[0], cd[1], n, m, out I1);
            NumbericalIntegrationDifferentiation.Integral_Simpson_xy2(f, ab[0], ab[1], cd[0], cd[1], n, m, out I2);

            Console.WriteLine($"标准值                 ：\t{StandardX}");
            Console.WriteLine($"二重定积分辛普森求积公式 :\t{I1}");
            Console.WriteLine($"二重定积分辛普森求积公式2:\t{I2}");
            //Console.WriteLine($"龙贝格公式 求积      :\t{I3}");
            //Console.WriteLine($"变步长辛普森求积  :\t{I3}");
            Assert.IsTrue(I1.EqualsEx(StandardX, 1e-3));
            Assert.IsTrue(I2.EqualsEx(StandardX, 1e-3));
            //Assert.IsTrue(I3.EqualsEx(StandardX, 1e-3));
            //Assert.IsTrue(I2.EqualsEx(StandardX, 1e-3));
            //Assert.IsTrue(I3.EqualsEx(StandardX, 1e-4));

        }

        [TestMethod]
        public void Example_5_8()
        {
            var f = new F(x => Math.Pow(x, 2) * Math.Pow(Math.E, x));
            double x = 1.0;
            double h = 0.1;
            double sdx = 8.1548455;
            double sddx = 19.027973;
            double _dx1, _ddx1;
            double eps = 1e-8;
            NumbericalIntegrationDifferentiation.Difference_Finite(f, x, h, eps, out _dx1, out _ddx1);

            var df = new F(x => Math.Pow(Math.E, x) * (2 * x + x * x));
            var ddf = new F(x => Math.Pow(Math.E, x) * (2 + 4 * x + x * x));
            double Rdx = df(x);
            double Rddx = ddf(x);

            Console.WriteLine($"标准值：\t{Rdx}\t{Rddx}");
            Console.WriteLine($"计算值：\t{_dx1}\t{_ddx1}");
            Console.WriteLine($"误差值：\t{_dx1 - Rdx}\t{_ddx1 - Rddx}");
            Assert.IsTrue(_dx1.EqualsEx(Rdx, 1e-3));
            Assert.IsTrue(_ddx1.EqualsEx(Rddx, 1e-3));
        }
    }
}
